/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */
#include "drv_i2s.h"

dma_channel_type *i2s_dma = DMA1_CHANNEL3;
confirm_state i2s_txBusy_flag = FALSE;

uint16_t i2s1_buffer_tx[32] = {0x0102, 0x0304, 0x0506, 0x0708, 0x090A, 0x0B0C,
                               0x0D0E, 0x0F10, 0x1112, 0x1314, 0x1516, 0x1718,
                               0x191A, 0x1B1C, 0x1D1E, 0x1F20, 0x2122, 0x2324,
                               0x2526, 0x2728, 0x292A, 0x2B2C, 0x2D2E, 0x2F30,
                               0x3132, 0x3334, 0x3536, 0x3738, 0x393A, 0x3B3C,
                               0x3D3E, 0x3F40};
uint16_t i2s2_buffer_rx[32];
volatile error_status transfer_status = ERROR;

static void gpio_config(void);
static void i2s_config(void);
error_status buffer_compare(uint16_t *pbuffer1, uint16_t *pbuffer2, uint16_t buffer_length);

struct rt_semaphore i2s_busy;

/**
 * @brief  buffer_compare function.
 * @param  none
 * @retval the result of compare
 */
error_status buffer_compare(uint16_t *pbuffer1, uint16_t *pbuffer2, uint16_t buffer_length)
{
    while (buffer_length--)
    {
        if (*pbuffer1 != *pbuffer2)
        {
            return ERROR;
        }

        pbuffer1++;
        pbuffer2++;
    }
    return SUCCESS;
}

/**
 * @brief  i2s configuration.
 * @param  none
 * @retval none
 */
static void i2s_config(void)
{
    dma_init_type dma_init_struct;
    i2s_init_type i2s_init_struct;

    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    // dma_reset(DMA1_CHANNEL4);
    dma_reset(DMA1_CHANNEL3);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = 32;
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_base_addr = (uint32_t)i2s1_buffer_tx;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&(SPI1->dt);
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL3, &dma_init_struct);

    // dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    // dma_init_struct.memory_base_addr = (uint32_t)i2s2_buffer_rx;
    // dma_init_struct.peripheral_base_addr = (uint32_t)&(SPI2->dt);
    // dma_init(DMA1_CHANNEL4, &dma_init_struct);

    crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
    // crm_periph_clock_enable(CRM_SPI2_PERIPH_CLOCK, TRUE);
    i2s_default_para_init(&i2s_init_struct);
    i2s_init_struct.audio_protocol = I2S_AUDIO_PROTOCOL_PHILLIPS;
    i2s_init_struct.data_channel_format = I2S_DATA_16BIT_CHANNEL_16BIT;
    i2s_init_struct.mclk_output_enable = TRUE;
    i2s_init_struct.audio_sampling_freq = I2S_AUDIO_FREQUENCY_96K;
    i2s_init_struct.clock_polarity = I2S_CLOCK_POLARITY_HIGH;
    i2s_init_struct.operation_mode = I2S_MODE_MASTER_TX;
    i2s_init(SPI1, &i2s_init_struct);

    // i2s_init_struct.operation_mode = I2S_MODE_SLAVE_RX;
    // i2s_init(SPI2, &i2s_init_struct);

    // dma_channel_enable(DMA1_CHANNEL3, TRUE);
    // dma_channel_enable(DMA1_CHANNEL4, TRUE);
    // spi_i2s_dma_receiver_enable(SPI2, TRUE);

    i2s_enable(SPI1, TRUE);
    // i2s_enable(SPI2, TRUE);

    dma_interrupt_enable(DMA1_CHANNEL3, DMA_FDT_INT, TRUE);
    nvic_irq_enable(DMA1_Channel3_IRQn, 0, 2);
}
static void i2s_transfer(void *memAddr, uint32_t memSize)
{
    dma_init_type dma_init_struct;
    // i2s_init_type i2s_init_struct;

    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    dma_reset(DMA1_CHANNEL3);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = memSize;
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_base_addr = (uint32_t)memAddr;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&(SPI1->dt);
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL3, &dma_init_struct);

    dma_interrupt_enable(DMA1_CHANNEL3, DMA_FDT_INT, TRUE);
    nvic_irq_enable(DMA1_Channel3_IRQn, 0, 2);
    dma_channel_enable(DMA1_CHANNEL3, TRUE);
}
/**
 * @brief  gpio configuration.
 * @param  none
 * @retval none
 */
static void gpio_config(void)
{
    gpio_init_type gpio_initstructure;
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

    /* master ws pin */
    gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_initstructure.gpio_pull = GPIO_PULL_UP;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins = GPIO_PINS_4;
    gpio_init(GPIOA, &gpio_initstructure);

    /* master ck pin */
    gpio_initstructure.gpio_pull = GPIO_PULL_DOWN;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_pins = GPIO_PINS_5;
    gpio_init(GPIOA, &gpio_initstructure);

    /* master sd pin */
    gpio_initstructure.gpio_pull = GPIO_PULL_DOWN;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_pins = GPIO_PINS_7;
    gpio_init(GPIOA, &gpio_initstructure);

    /* master mck pin */
    gpio_initstructure.gpio_pull = GPIO_PULL_DOWN;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_pins = GPIO_PINS_0;
    gpio_init(GPIOB, &gpio_initstructure);

    /* slave ws pin */
    gpio_initstructure.gpio_pull = GPIO_PULL_UP;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_pins = GPIO_PINS_12;
    gpio_init(GPIOB, &gpio_initstructure);

    /* slave ck pin */
    gpio_initstructure.gpio_pull = GPIO_PULL_DOWN;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_pins = GPIO_PINS_13;
    gpio_init(GPIOB, &gpio_initstructure);

    /* slave sd pin */
    gpio_initstructure.gpio_pull = GPIO_PULL_DOWN;
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_pins = GPIO_PINS_15;
    gpio_init(GPIOB, &gpio_initstructure);
}
// Pa0  1   2三个灯，还有一个电源灯常亮

void i2s_dma_init(void)
{
    i2s_txBusy_flag = 0;
    gpio_config();
    i2s_config();
    spi_i2s_dma_transmitter_enable(SPI1, TRUE);
    rt_sem_init(&i2s_busy, "i2sTx", 10, 0);

    // rt_kprintf("i2s_dma_init\n");
}
void i2s_dma_tx(int16_t *data, uint16_t size)
{
    if (i2s_txBusy_flag)
    {
        rt_sem_take(&i2s_busy, RT_WAITING_FOREVER);
    }
    // while (i2s_txBusy_flag == 1)
    // {
    //     /* code */
    //     // rt_kprintf("busy");
    //     // rt_thread_mdelay(1);
    // }
    // i2s_fast_init();
    // rt_kprintf("\n >> D1C3 >>\n");
    // i2s_dma->maddr = (uint32_t)data;
    // i2s_dma->dtcnt = size;
    // i2s_dma->ctrl_bit.chen = 1;
    // dma_channel_enable(DMA1_CHANNEL3, TRUE);
    // i2s_enable(SPI1, TRUE);
    i2s_transfer(data, size);
    i2s_txBusy_flag = 1;
}
void DMA1_Channel3_IRQHandler(void)
{
    if (dma_interrupt_flag_get(DMA1_FDT3_FLAG) != RESET)
    {
        dma_flag_clear(DMA1_FDT3_FLAG);
        // rt_kprintf("\n << D1C3 <<\n");
        i2s_txBusy_flag = 0;
        rt_sem_release(&i2s_busy);
    }
}

/**
 * @}
 */

/**
 * @}
 */
